home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 2002 November / SGI Freeware 2002 November - Disc 2.iso / dist / fw_glimpse.idb / usr / freeware / src / glimpse-3.0 / index / partition.c.z / partition.c
C/C++ Source or Header  |  1997-09-09  |  32KB  |  940 lines

  1. /* Copyright (c) 1994 Sun Wu, Udi Manber, Burra Gopal.  All Rights Reserved. */
  2. /* ./glimpse/index/partition.c */
  3. #include "glimpse.h"
  4. #include <sys/stat.h>
  5.  
  6. extern int DeleteFromIndex;
  7. extern int FastIndex;
  8. extern int FilenamesOnStdin;
  9. extern char INDEX_DIR[MAX_LINE_LEN];
  10. extern char sync_path[MAX_LINE_LEN];
  11. extern int file_num;    /* the number of files */
  12. extern int new_file_num; /* the new number of files after purging some from index */
  13. extern char **name_list[MAXNUM_INDIRECT]; /* to store the file names */
  14. extern int  *size_list[MAXNUM_INDIRECT]; /* store size of each file */
  15. extern int  p_table[MAX_PARTITION];    /* partition table, the i-th partition begins at p_table[i] and ends at p_tables[i+1] */
  16. extern int  p_size_list[MAX_PARTITION];    /* sum of the sizes of the files in each partition */
  17. extern int  part_num;    /* number of partitions, 1 initially since partition # 0 is not accessed */
  18.  
  19. extern int built_filename_hashtable;
  20. extern name_hashelement *name_hashtable[MAX_4K_HASH];
  21. extern int total_size; /* total size of the directory */
  22. extern int total_deleted; /* number of files being deleted */
  23. int  part_size=DEFAULT_PART_SIZE;    /* partition size */
  24. int  new_partition;
  25. int  files_per_partition;
  26. int  files_in_partition;
  27.  
  28. char patbuf[MAX_PAT];
  29. extern unsigned char *src_index_buf;
  30. extern unsigned char *dest_index_buf;
  31. extern int REAL_PARTITION, REAL_INDEX_BUF, MAX_ALL_INDEX, FILEMASK_SIZE;
  32. extern int memory_usage;
  33. extern struct indices    *deletedlist;
  34.  
  35. extern  FILE    *STATFILE;
  36. extern  FILE    *MESSAGEFILE;
  37.  
  38. extern struct stat excstbuf;
  39. extern struct stat incstbuf;
  40.  
  41. extern int GenerateHash;
  42. extern int KeepFilenames;
  43. extern int OneFilePerBlock;
  44. extern int ByteLevelIndex;
  45. extern int StructuredIndex;
  46. extern int attr_num;
  47. extern char INDEX_DIR[MAX_LINE_LEN];
  48. extern int AddToIndex;
  49. extern int IndexableFile;
  50. extern int BuildTurbo;
  51.  
  52. char *exin_argv[8];
  53. int exin_argc;
  54. char current_dir_buf[2*MAX_LINE_LEN + 4];    /* must have space to store pattern after directory name */
  55. unsigned char dummypat[MAX_PAT];
  56. int dummylen;
  57. FILE *dummyout;
  58.  
  59. partition(dir_num, dir_name)
  60. char **dir_name;
  61. int  dir_num;
  62. {
  63.     int num_pat=0;
  64.     int num_inc=0;
  65.     int len;
  66.     int  pat_len[MAX_EXCLUSIVE];
  67.     int  inc_len[MAX_EXCLUSIVE];
  68.     CHAR *inc[MAX_INCLUSIVE];    /* store the patterns used to mask in files */
  69.     CHAR *pat[MAX_EXCLUSIVE];     /* store the patterns that are used to
  70.                      mask out those files that are not to
  71.                      be indexed  */
  72.     int MinPartNum;         /* minimum number of partitions */
  73.     int i=0, j;
  74.     int subtotal=0;
  75.     int pdx = 0;             /* index pointer for p_table */
  76.     FILE *patfile;     /* file descriptor for prohibit pattern file */
  77.     FILE *incfile;    /* file descriptor for include pattern file */
  78.     char *current_dir;    /* must have '\n' before directory name */
  79.     char s[MAX_LINE_LEN];
  80.     char working_dir[MAX_LINE_LEN];
  81.     struct stat sbuf;
  82.  
  83.     current_dir_buf[0] = '\n';
  84.     current_dir_buf[1] = '\0';
  85.     current_dir = ¤t_dir_buf[1];
  86.     /* if (IndexableFile) goto directlytofsize; */
  87.  
  88.     if ((dummyout = fopen("/dev/null", "w")) == NULL) return -1;
  89.     exin_argv[0] = "glimpseindex";
  90.     exin_argv[1] = "dummypat";
  91.     exin_argc = 2;
  92.     if ((dummylen = memagrep_init(exin_argc, exin_argv, MAX_PAT, dummypat)) <= 0) return -1;    /* exclude/include pattern search */
  93.  
  94.     sprintf(s, "%s/%s", INDEX_DIR, PROHIBIT_LIST);
  95.     patfile = fopen(s, "r");
  96.     if(patfile == NULL) {
  97.     /* fprintf(stderr, "can't open exclude-pattern file\n"); -- no need! */
  98.     num_pat = 0;
  99.     }
  100.     else {
  101.     while((num_pat < MAX_EXCLUSIVE) && fgets(patbuf, MAX_PAT, patfile)) {
  102.         if ((len = strlen(patbuf)) < 1) continue;
  103.         patbuf[len-1] = '\0';
  104.         if ((pat_len[num_pat] = convert2agrepregexp(patbuf, len-1)) == 0) continue;
  105.         pat[num_pat++] = (unsigned char *) strdup(patbuf);
  106.     }
  107.     fclose(patfile);
  108.     }
  109. #if    0
  110.     printf("num_pat %d\n", num_pat);
  111.     for(i=0; i<num_pat; i++) printf("len=%d pat=%s\n", pat_len[i], pat[i]);
  112.     printf("memagrep=%d\n", memagrep_search(-pat_len[0], pat[0], 17, "\n.glimpse_index\nasdfk", 0, stdout));
  113. #endif
  114.  
  115.     sprintf(s, "%s/%s", INDEX_DIR, INCLUDE_LIST);
  116.     incfile = fopen(s, "r");
  117.     if(incfile == NULL) {
  118.     /* fprintf(stderr, "can't open include-pattern file\n"); -- no need! */
  119.     num_inc = 0;
  120.     }
  121.     else {
  122.     while((num_inc < MAX_INCLUSIVE) && fgets(patbuf, MAX_PAT, incfile)) {
  123.         if ((len = strlen(patbuf)) < 1) continue;
  124.         patbuf[len-1] = '\0';
  125.         if ((inc_len[num_inc] = convert2agrepregexp(patbuf, len-1)) == 0) continue;
  126.         inc[num_inc++] = (unsigned char *) strdup(patbuf);
  127.     }
  128.     fclose(incfile);
  129.     }
  130. #if    0
  131.     printf("num_inc %d\n", num_inc);
  132.     for(i=0; i<num_inc; i++) printf("len=%d inc=%s\n", inc_len[i], inc[i]);
  133. #endif
  134.  
  135. #ifdef    SW_DEBUG
  136.     printf("dir_num = %d", dir_num-1);
  137. #endif
  138. directlytofsize:
  139.     if (dir_num <= 1) while (fgets(current_dir, MAX_LINE_LEN, stdin) == current_dir) {
  140.     current_dir[strlen(current_dir)-1] = '\0';    /* overwrite \n with \0 */
  141.  
  142.     /* Get absolute path name of the directory or file being indexed */
  143.     if (-1 == stat(current_dir, &sbuf)) {
  144.         fprintf(stderr, "permission denied or non-existent: %s\n", current_dir);
  145.         continue;
  146.     }
  147.     if ((S_ISDIR(sbuf.st_mode)) && (current_dir[0] != '/')) {
  148.         getcwd(working_dir, MAX_LINE_LEN - 1);
  149.         if (-1 == chdir(current_dir)) {
  150.         fprintf(stderr, "Cannot chdir to %s\n", current_dir);
  151.         continue;
  152.         }
  153.         getcwd(current_dir, MAX_LINE_LEN - 1);
  154.         chdir(working_dir);
  155.     }
  156.  
  157.     if (!IndexableFile) printf("Indexing \"%s\" ...\n", current_dir);
  158.         fsize(current_dir, pat, pat_len, num_pat, inc, inc_len, num_inc, 1); /* the file names will be in name_list[] */
  159.     }
  160.     else for(i=1; i<dir_num; i++) {
  161.         strcpy(current_dir, dir_name[i]);
  162.  
  163.     /* Get absolute path name of the directory or file being indexed */
  164.     if (-1 == stat(current_dir, &sbuf)) {
  165.         fprintf(stderr, "permission denied or non-existent: %s\n", current_dir);
  166.         continue;
  167.     }
  168.     if ((S_ISDIR(sbuf.st_mode)) && (current_dir[0] != '/')) {
  169.         getcwd(working_dir, MAX_LINE_LEN - 1);
  170.         if (-1 == chdir(current_dir)) {
  171.         fprintf(stderr, "Cannot chdir to %s\n", current_dir);
  172.         continue;
  173.         }
  174.         getcwd(current_dir, MAX_LINE_LEN - 1);
  175.         chdir(working_dir);
  176.     }
  177.  
  178.     if (!IndexableFile) {
  179.         if (!DeleteFromIndex) printf("Indexing \"%s\" ...\n", current_dir);
  180.     }
  181.         fsize(current_dir, pat, pat_len, num_pat, inc, inc_len, num_inc, 1); /* the file names will be in name_list[] */
  182.     }
  183.     if (IndexableFile) return 0;
  184.  
  185.     for(i=0; i<file_num; i++) total_size += LIST_GET(size_list, i);
  186.     for(i=0; i<file_num; i++) if (LIST_GET(name_list, i) == NULL) total_deleted ++;
  187.     if (DeleteFromIndex) {
  188.     if (total_size <= 0) {
  189.         fprintf(STATFILE, "#of files being deleted = %d, Total #of files = %d\n", total_deleted, file_num - total_deleted);
  190.         printf("\n#of files being deleted = %d, Total #of files = %d\n", total_deleted, file_num - total_deleted);    /* the only output the user sees */
  191.     }
  192.     else {
  193.         fprintf(STATFILE, "Size of files being indexed = %d B, #of files being deleted = %d, Total #of files = %d\n", total_size, total_deleted, file_num - total_deleted);
  194.         printf("\nSize of files being indexed = %d B, #of files being deleted = %d, Total #of files = %d\n", total_size, total_deleted, file_num - total_deleted);    /* the only output the user sees */
  195.     }
  196.     }
  197.     else {
  198.     fprintf(STATFILE, "Size of files being indexed = %d B, Total #of files = %d\n", total_size, file_num);
  199.     printf("\nSize of files being indexed = %d B, Total #of files = %d\n", total_size, file_num);    /* the only output the user sees */
  200.     }
  201.  
  202. #ifdef    SW_DEBUG
  203.     for (i=0; i<file_num; i++)
  204.     printf("name_list[%d] = %s, size=%d\n", i, LIST_GET(name_list, i), LIST_GET(size_list, i));
  205. #endif    /*SW_DEBUG*/
  206.  
  207.     for (i=0; i<num_inc; i++) {
  208. #if    BG_DEBUG
  209.     memory_usage -= strlen(inc) + 2;
  210. #endif    /*BG_DEBUG*/
  211.     my_free(inc[i], 0);
  212.     }
  213.     for (i=0; i<num_pat; i++) {
  214. #if    BG_DEBUG
  215.     memory_usage -= strlen(pat) + 2;
  216. #endif    /*BG_DEBUG*/
  217.     my_free(pat[i], 0);
  218.     }
  219.  
  220.     /* Life (algorithm) is much simpler, but encode/decode (I/O) is more complex: the p_table is irrelevant */
  221.     if (OneFilePerBlock)
  222.     return 0;
  223.  
  224.     /* Now put the files into partitions */
  225.     i=0;
  226.     part_size = total_size / MaxNumPartition;
  227.     if (part_size <= 0) part_size = total_size;
  228.     LIST_ADD(size_list, file_num, part_size, int);
  229.     if (file_num / 2 <= 1) {
  230.     p_table[0] = 0;
  231.     p_table[1] = 0;
  232.     p_table[2] = file_num;
  233.     part_num = 2;
  234.     return 0;
  235.     }
  236.  
  237.     MinPartNum = (200 < file_num/2)? 200 : file_num/2;
  238.     while(part_num < MinPartNum) {
  239.         pdx = 0;
  240.     i = 0;
  241.         subtotal = 0;
  242.         while ((i < file_num) && (pdx < MAX_PARTITION)) {
  243.         if((pdx == 0) || (pdx == '\n')) {
  244.         /*
  245.          * So that there cannot be a partition #'\n' and a '\n' can indicate
  246.          * the end of the list of partition#s after the WORD_END_MARK.
  247.          * Also, partition#0 is not accessed so that sort does not
  248.          * ignore the partitions after partition# 0!
  249.          */
  250.         p_table[pdx++] = i;
  251.         continue;
  252.         }
  253.         p_table[pdx++] = i;
  254.             while(subtotal < part_size) {
  255.                 subtotal += LIST_GET(size_list, i);
  256.         i++;
  257.             }
  258. #ifdef    SW_DEBUG
  259.         printf("pdx=%d part_num=%d i=%d subtotal=%d\n", pdx, part_num, i, subtotal);
  260. #endif
  261.             subtotal = 0;
  262.         }
  263.     part_num = pdx;
  264. #if    0
  265.     printf("part_num = %d part_size = %d\n", part_num, part_size);
  266. #endif
  267.     part_size = part_size * 0.9;
  268.         LIST_ADD(size_list, file_num, part_size, int);
  269.     }
  270.     p_table[pdx] = file_num;
  271.  
  272.     /* Calculate partition sizes for later output into statistics */
  273.     for (i=0; i<= part_num; i++)
  274.     for (j = p_table[i]; j<p_table[i+1]; j++)
  275.         p_size_list[i] += LIST_GET(size_list, j);
  276.  
  277.     return 0;
  278. }
  279.  
  280. int printed_warning = 0;
  281.  
  282. /*
  283.  * Difference from above: does not build a new partition table:
  284.  * adds to the existing one (see glimpse.c, options -a and -f).
  285.  * -- added on dec 7th '93
  286.  */
  287. oldpartition(dir_num, dir_name)
  288. char **dir_name;
  289. int  dir_num;
  290. {
  291.     int num_pat=0;
  292.     int num_inc=0;
  293.     int len;
  294.     int  pat_len[MAX_EXCLUSIVE];
  295.     int  inc_len[MAX_EXCLUSIVE];
  296.     CHAR *inc[MAX_INCLUSIVE];    /* store the patterns used to mask in files */
  297.     CHAR *pat[MAX_EXCLUSIVE];     /* store the patterns that are used to
  298.                      mask out those files that are not to
  299.                      be indexed  */
  300.     int i=0;
  301.     FILE *patfile;     /* file descriptor for prohibit pattern file */
  302.     FILE *incfile;    /* file descriptor for include pattern file */
  303.     char *current_dir;    /* must have '\n' before directory name */
  304.     char s[MAX_LINE_LEN];
  305.     char working_dir[MAX_LINE_LEN];
  306.     struct stat sbuf;
  307.  
  308.     current_dir_buf[0] = '\n';
  309.     current_dir_buf[1] = '\0';
  310.     current_dir = ¤t_dir_buf[1];
  311.  
  312.     if ((dummyout = fopen("/dev/null", "w")) == NULL) return -1;
  313.     exin_argv[0] = "glimpseindex";
  314.     exin_argv[1] = "dummypat";
  315.     exin_argc = 2;
  316.     if ((dummylen = memagrep_init(exin_argc, exin_argv, MAX_PAT, dummypat)) <= 0) return -1;    /* exclude/include pattern search */
  317.  
  318.     sprintf(s, "%s/%s", INDEX_DIR, PROHIBIT_LIST);
  319.     patfile = fopen(s, "r");
  320.     if(patfile == NULL) {
  321.     /* fprintf(stderr, "can't open exclude-pattern file\n"); -- no need! */
  322.     num_pat = 0;
  323.     }
  324.     else {
  325.     stat(s, &excstbuf);
  326.     while((num_pat < MAX_EXCLUSIVE) && fgets(patbuf, MAX_PAT, patfile)) {
  327.         if ((len = strlen(patbuf)) < 1) continue;
  328.         patbuf[len-1] = '\0';
  329.         if ((pat_len[num_pat] = convert2agrepregexp(patbuf, len-1)) == 0) continue;
  330.         pat[num_pat++] = (unsigned char *) strdup(patbuf);
  331.     }
  332.     fclose(patfile);
  333.     }
  334. #if    0
  335.     printf("num_pat %d\n", num_pat);
  336.     for(i=0; i<num_pat; i++) printf("len=%d pat=%s\n", pat_len[i], pat[i]);
  337. #endif
  338.  
  339.     sprintf(s, "%s/%s", INDEX_DIR, INCLUDE_LIST);
  340.     incfile = fopen(s, "r");
  341.     if(incfile == NULL) {
  342.     /* fprintf(stderr, "can't open include-pattern file\n"); -- no need! */
  343.     num_inc = 0;
  344.     }
  345.     else {
  346.     stat(s, &incstbuf);
  347.     while((num_inc < MAX_INCLUSIVE) && fgets(patbuf, MAX_PAT, incfile)) {
  348.         if ((len = strlen(patbuf)) < 1) continue;
  349.         patbuf[len-1] = '\0';
  350.         if ((inc_len[num_inc] = convert2agrepregexp(patbuf, len-1)) == 0) continue;
  351.         inc[num_inc++] = (unsigned char *) strdup(patbuf);
  352.     }
  353.     fclose(incfile);
  354.     }
  355. #if    0
  356.     printf("num_inc %d\n", num_inc);
  357.     for(i=0; i<num_inc; i++) printf("len=%d inc=%s\n", inc_len[i], inc[i]);
  358. #endif
  359.  
  360. #ifdef    SW_DEBUG
  361.     printf("dir_num = %d part_num = %d", dir_num-1, part_num);
  362. #endif
  363.  
  364.     if (!OneFilePerBlock) {    /* Worry about partitions */
  365.     files_per_partition = ((file_num - 1)/part_num) + 1;    /* approximate only but gives a fair idea... */
  366.     files_in_partition = 0;
  367.     new_partition = part_num;    /* part_num itself is guaranteed to be <= MaxNumPartition */
  368.  
  369.     if (new_partition + 1 > MaxNumPartition) {
  370.         printed_warning = 1;
  371.         if (AddToIndex) {
  372.         fprintf(MESSAGEFILE, "Warning: partition-table overflow! Fresh indexing recommended.\n");
  373.         }
  374.         else {
  375.         fprintf(MESSAGEFILE, "Warning: partition-table overflow! Commencing fresh indexing...\n");
  376.         return partition(dir_num, dir_name);
  377.         }
  378.     }
  379.     }
  380.  
  381.     if ((dir_num <= 1) && FilenamesOnStdin) while (fgets(current_dir, MAX_LINE_LEN, stdin) == current_dir) {
  382.     current_dir[strlen(current_dir)-1] = '\0';    /* overwrite \n with \0 */
  383.  
  384.     /* Get absolute path name of the directory or file being indexed */
  385.     if (-1 == stat(current_dir, &sbuf)) {
  386.         fprintf(stderr, "permission denied or non-existent: %s\n", current_dir);
  387.         continue;
  388.     }
  389.     if ((S_ISDIR(sbuf.st_mode)) && (current_dir[0] != '/')) {
  390.         getcwd(working_dir, MAX_LINE_LEN - 1);
  391.         if (-1 == chdir(current_dir)) {
  392.         fprintf(stderr, "Cannot chdir to %s\n", current_dir);
  393.         continue;
  394.         }
  395.         getcwd(current_dir, MAX_LINE_LEN - 1);
  396.         chdir(working_dir);
  397.     }
  398.  
  399.     if (!DeleteFromIndex) printf("Indexing \"%s\" ...\n", current_dir);
  400.         fsize(current_dir, pat, pat_len, num_pat, inc, inc_len, num_inc, 1); /* the file names will be in name_list[] */
  401.     }
  402.     else for(i=1; i<dir_num; i++) {
  403.         strcpy(current_dir, dir_name[i]);
  404.  
  405.     /* Get absolute path name of the directory or file being indexed */
  406.     if (-1 == stat(current_dir, &sbuf)) {
  407.         fprintf(stderr, "permission denied or non-existent: %s\n", current_dir);
  408.         continue;
  409.     }
  410.     if ((S_ISDIR(sbuf.st_mode)) && (current_dir[0] != '/')) {
  411.         getcwd(working_dir, MAX_LINE_LEN - 1);
  412.         if (-1 == chdir(current_dir)) {
  413.         fprintf(stderr, "Cannot chdir to %s\n", current_dir);
  414.         continue;
  415.         }
  416.         getcwd(current_dir, MAX_LINE_LEN - 1);
  417.         chdir(working_dir);
  418.     }
  419.  
  420.     if (!DeleteFromIndex) printf("Indexing \"%s\" ...\n", current_dir);
  421.         if (-1 == fsize(current_dir, pat, pat_len, num_pat, inc, inc_len, num_inc, 1)) { /* the file names will be in name_list[] */
  422.         return -1;
  423.     }
  424.     }
  425.  
  426.     if (!OneFilePerBlock) {
  427.     p_table[new_partition] = file_num;
  428.     part_num = new_partition;
  429.     }
  430.  
  431.     for (i=0; i<num_inc; i++) {
  432. #if    BG_DEBUG
  433.     memory_usage -= strlen(inc) + 2;
  434. #endif    /*BG_DEBUG*/
  435.     my_free(inc[i], 0);
  436.     }
  437.     for (i=0; i<num_pat; i++) {
  438. #if    BG_DEBUG
  439.     memory_usage -= strlen(pat) + 2;
  440. #endif    /*BG_DEBUG*/
  441.     my_free(pat[i], 0);
  442.     }
  443.  
  444.     for(i=0; i<file_num; i++) total_size += LIST_GET(size_list, i);
  445.     for(i=0; i<file_num; i++) if (LIST_GET(name_list, i) == NULL) total_deleted ++;
  446.     if (DeleteFromIndex) {
  447.     if (total_size <= 0) {
  448.         fprintf(STATFILE, "#of files being deleted = %d, Total #of files = %d\n", total_deleted, file_num - total_deleted);
  449.         printf("\n#of files being deleted = %d, Total #of files = %d\n", total_deleted, file_num - total_deleted);    /* the only output the user sees */
  450.     }
  451.     else {
  452.         fprintf(STATFILE, "Size of files being indexed = %d B, #of files being deleted = %d, Total #of files = %d\n", total_size, total_deleted, file_num - total_deleted);
  453.         printf("\nSize of files being indexed = %d B, #of files being deleted = %d, Total #of files = %d\n", total_size, total_deleted, file_num - total_deleted);    /* the only output the user sees */
  454.     }
  455.     }
  456.     else {
  457.     fprintf(STATFILE, "Size of files being indexed = %d B, Total #of files = %d\n", total_size, file_num);
  458.     printf("\nSize of files being indexed = %d B, Total #of files = %d\n", total_size, file_num);    /* the only output the user sees */
  459.     }
  460.  
  461. #ifdef    SW_DEBUG
  462.     for (i=0; i<file_num; i++)
  463.     printf("name_list[%d] = %s, size=%d\n", i, LIST_GET(name_list, i), LIST_GET(size_list, i));
  464. #endif    /*SW_DEBUG*/
  465.  
  466.     return 0;
  467. }
  468.  
  469. save_data_structures()
  470. {
  471.     int    i;
  472.     char s[MAX_LINE_LEN], s1[MAX_LINE_LEN];
  473.     FILE *f_out;
  474.     FILE *p_out;
  475.     int j;
  476.     unsigned char c;
  477.     FILE *i_in;
  478.     FILE *i_out;
  479.     int offset, index;
  480.     char indexnumberbuf[256];
  481.     int    onefileperblock, structuredindex;
  482.     int name_list_size = file_num;
  483.     name_hashelement *e;
  484.  
  485. #if    0
  486.     fflush(stdout);
  487.     printf("BEFORE SAVE_DATA_STRUCTURES:\n");
  488.     sprintf(s, "exec %s -lg .glimpse_*", SYSTEM_LS);
  489.     system(s);
  490.     sprintf(s, "exec %s .glimpse_index", SYSTEM_HEAD);
  491.     system(s);
  492.     getchar();
  493. #endif    /*0*/
  494.  
  495.     if ((new_file_num >= 0) && (new_file_num <= file_num)) file_num = new_file_num;    /* only if purge_index() was called: -f/-a/-d only */
  496.     /* Dump attributes */
  497.     if (StructuredIndex && (attr_num > 0)) {
  498.     int    ret;
  499.     sprintf(s, "%s/%s", INDEX_DIR, ATTRIBUTE_FILE);
  500.     if (-1 == (ret = attr_dump_names(s))) {
  501.         fprintf(stderr, "can't open %s for writing\n", s);
  502.         exit(2);
  503.     }
  504.     }
  505.  
  506.     /* Dump partition table; change index if necessary */
  507.     sprintf(s, "%s/%s", INDEX_DIR, P_TABLE);
  508.     if((p_out = fopen(s, "w")) == NULL) {
  509.     fprintf(stderr, "can't open for writing: %s\n", s);
  510.     exit(2);
  511.     }
  512.     if (!OneFilePerBlock) {
  513. #ifdef SW_DEBUG
  514.     printf("part_num = %d, part_size = %d\n", part_num, part_size);
  515. #endif
  516.     for(i=0; i<=part_num; i++) {
  517.         /* Assumes sizeof(int) is 32bits, which is true even for ALPHA */
  518.         putc((p_table[i] & 0xff000000) >> 24, p_out);
  519.         putc((p_table[i] & 0x00ff0000) >> 16, p_out);
  520.         putc((p_table[i] & 0x0000ff00) >> 8, p_out);
  521.         if (putc((p_table[i] & 0x000000ff), p_out) == EOF) {
  522.         fprintf(stderr, "Error: write failed at %s:%d\n", __FILE__, __LINE__);
  523.         exit(2);
  524.         }
  525.         if (i==part_num) break;
  526.         if (p_table[i] == p_table[i+1]) {
  527.         fprintf(STATFILE, "part_num = %d, files = none, part_size = 0\n",i);
  528.         continue;
  529.         }
  530.         fprintf(STATFILE, "part_num = %d, files = %d .. %d, part_size = %d\n",
  531.         i, p_table[i], p_table[i+1] - 1, p_size_list[i]);
  532.     }
  533.  
  534.     if (StructuredIndex) {    /* check if we can reduce default 2B attributeids to smaller ones */
  535.         sprintf(s, "%s/.glimpse_split.%d", INDEX_DIR, getpid());
  536.         if((i_out = fopen(s, "w")) == NULL) {
  537.         fprintf(stderr, "can't open %s for writing\n", s);
  538.         exit(2);
  539.         }
  540.         sprintf(s, "%s/%s", INDEX_DIR, INDEX_FILE);
  541.         if((i_in = fopen(s, "r")) == NULL) {
  542.         fprintf(stderr, "can't open %s for reading\n", s);
  543.         exit(2);
  544.         }
  545.  
  546.         /* modified the original in glimpse's main.c */
  547.         fgets(indexnumberbuf, 256, i_in);
  548.         fputs(indexnumberbuf, i_out);
  549.         fscanf(i_in, "%%%d\n", &onefileperblock);
  550.         fprintf(i_out, "%%%d\n", onefileperblock);    /* If #of files change, then they are added to a new partition, which is updated above */
  551.         fscanf(i_in, "%%%d\n", &structuredindex);
  552.         if (structuredindex <= 0) structuredindex = 0;
  553.         fprintf(i_out, "%%%d\n", attr_num);    /* attributes might have been added during last merge */
  554.  
  555.         while(fgets(src_index_buf, REAL_INDEX_BUF, i_in)) {
  556.         j = 0;
  557.         while ((j < REAL_INDEX_BUF) && (src_index_buf[j] != WORD_END_MARK) && (src_index_buf[j] != ALL_INDEX_MARK) && (src_index_buf[j] != '\0') && (src_index_buf[j] != '\n')) j++;
  558.         if ((j >= REAL_INDEX_BUF) || (src_index_buf[j] == '\0') || (src_index_buf[j] == '\n')) continue;
  559.         /* else it is WORD_END_MARK or ALL_INDEX_MARK */
  560.         c = src_index_buf[j+1];
  561.         src_index_buf[j+1] = '\0';
  562.         fputs(src_index_buf, i_out);
  563.         src_index_buf[j+1] = c;
  564.         index=decode16b((src_index_buf[j+1] << 8) | (src_index_buf[j+2]));
  565.         if ((attr_num > 0) && (attr_num < MaxNum8bPartition - 1)) {
  566.             putc(encode8b(index), i_out);
  567.         }
  568.         else if (attr_num > 0) {
  569.             putc(src_index_buf[j+1], i_out);
  570.             putc(src_index_buf[j+2], i_out);
  571.         }
  572.         j += 3;
  573.         if (fputs(src_index_buf+j, i_out) == EOF) {    /* Rest of the partitions information */
  574.             fprintf(stderr, "Error: write failed at %s:%d\n", __FILE__, __LINE__);
  575.             exit(2);
  576.         }
  577.         }
  578.  
  579.         fclose(i_in);
  580.         fflush(i_out);
  581.         fclose(i_out);
  582. #if    SFS_COMPAT
  583.         sprintf(s, "%s/.glimpse_split.%d", INDEX_DIR, getpid());
  584.         sprintf(s1, "%s/%s", INDEX_DIR, INDEX_FILE);
  585.         rename(s, s1);
  586. #else
  587.         sprintf(s, "exec %s %s/.glimpse_split.%d %s/%s", SYSTEM_MV, INDEX_DIR, getpid(), INDEX_DIR, INDEX_FILE);
  588.         system(s);
  589. #endif
  590.     }
  591.     }
  592.     else {
  593.     /* Don't care about individual file sizes in statistics since the user can look at it anyway by ls -l! */
  594.     sprintf(s, "%s/.glimpse_split.%d", INDEX_DIR, getpid());
  595.         if((i_out = fopen(s, "w")) == NULL) {
  596.         fprintf(stderr, "can't open %s for writing\n", s);
  597.         exit(2);
  598.         }
  599.     sprintf(s, "%s/%s", INDEX_DIR, INDEX_FILE);
  600.         if((i_in = fopen(s, "r")) == NULL) {
  601.         fprintf(stderr, "can't open %s for reading\n", s);
  602.         exit(2);
  603.         }
  604.  
  605.         /* modified the original in glimpse's main.c */
  606.         fgets(indexnumberbuf, 256, i_in);
  607.         fputs(indexnumberbuf, i_out);
  608.         fscanf(i_in, "%%%d\n", &onefileperblock);
  609.         if (ByteLevelIndex) fprintf(i_out, "%%-%d\n", file_num);    /* #of files might have changed due to -f/-a */
  610.     else fprintf(i_out, "%%%d\n", file_num);    /* This was the stupidest thing of all! */
  611.         fscanf(i_in, "%%%d\n", &structuredindex);
  612.         if (structuredindex <= 0) structuredindex = 0;
  613.         fprintf(i_out, "%%%d\n", attr_num);    /* attributes might have been added during last merge */
  614.  
  615.     part_size = 0;    /* current offset in the p_table file */
  616.     while(fgets(src_index_buf, REAL_INDEX_BUF, i_in)) {
  617.         j = 0;
  618.         while ((j < REAL_INDEX_BUF) && (src_index_buf[j] != WORD_END_MARK) && (src_index_buf[j] != ALL_INDEX_MARK) && (src_index_buf[j] != '\n')) j++;
  619.         if ((j >= REAL_INDEX_BUF) || (src_index_buf[j] == '\n')) continue;
  620.         /* else it is WORD_END_MARK or ALL_INDEX_MARK */
  621.         c = src_index_buf[j+1];
  622.         src_index_buf[j+1] = '\0';
  623.         fputs(src_index_buf, i_out);
  624.         src_index_buf[j+1] = c;
  625.         c = src_index_buf[j];
  626.         if (StructuredIndex) {
  627.         index = decode16b((src_index_buf[j+1] << 8) | (src_index_buf[j+2]));
  628.         if ((attr_num > 0) && (attr_num < MaxNum8bPartition - 1)) {
  629.             putc(encode8b(index), i_out);
  630.         }
  631.         else if (attr_num > 0) {
  632.             putc(src_index_buf[j+1], i_out);
  633.             putc(src_index_buf[j+2], i_out);
  634.         }
  635.         j += 2;
  636.         }
  637.         if (c == ALL_INDEX_MARK) {
  638.         putc(DONT_CONFUSE_SORT, i_out);
  639.         if (putc('\n', i_out) == EOF) {
  640.             fprintf(stderr, "Error: write failed at %s:%d\n", __FILE__, __LINE__);
  641.             exit(2);
  642.         }
  643.         continue;
  644.         }
  645.  
  646.         offset = encode32b(part_size);
  647.         putc((offset & 0xff000000) >> 24, i_out);    /* force big-endian */
  648.         putc((offset & 0x00ff0000) >> 16, i_out);
  649.         putc((offset & 0x0000ff00) >> 8, i_out);
  650.         putc((offset & 0x000000ff), i_out);
  651.         if (putc('\n', i_out) == EOF) {
  652.         fprintf(stderr, "Error: write failed at %s:%d\n", __FILE__, __LINE__);
  653.         exit(2);
  654.         }
  655.  
  656.         j++;    /* @first byte of the block numbers */
  657.         while((src_index_buf[j] != '\n') && (src_index_buf[j] != '\0')) {
  658.         putc(src_index_buf[j++], p_out);
  659.         part_size ++;
  660.         }
  661.         if (putc('\n', p_out) == EOF) {
  662.         fprintf(stderr, "Error: write failed at %s:%d\n", __FILE__, __LINE__);
  663.         exit(2);
  664.         }
  665.         part_size ++;
  666.     }
  667.     fclose(i_in);
  668.     fflush(i_out);
  669.     fclose(i_out);
  670. #if    SFS_COMPAT
  671.     sprintf(s, "%s/.glimpse_split.%d", INDEX_DIR, getpid());
  672.     sprintf(s1, "%s/%s", INDEX_DIR, INDEX_FILE);
  673.     rename(s, s1);
  674. #else
  675.     sprintf(s, "exec %s %s/.glimpse_split.%d %s/%s", SYSTEM_MV, INDEX_DIR, getpid(), INDEX_DIR, INDEX_FILE);
  676.     system(s);
  677. #endif
  678.     system(sync_path);    /* sync() has a BUG */
  679.     sprintf(s, "%s/%s", INDEX_DIR, INDEX_FILE);
  680.     if (BuildTurbo) dump_mini(s);
  681.     }
  682.     fflush(p_out);
  683.     fclose(p_out);
  684.  
  685.     /* Dump file names */
  686.     if (KeepFilenames) {
  687.     sprintf(s, "exec %s %s/%s %s/%s.prev", SYSTEM_CP, INDEX_DIR, NAME_LIST, INDEX_DIR, NAME_LIST);
  688.     system(s);
  689.     sprintf(s, "exec %s %s/%s %s/%s.prev", SYSTEM_CP, INDEX_DIR, NAME_LIST_INDEX, INDEX_DIR, NAME_LIST_INDEX);
  690.     system(s);
  691.     }
  692.     sprintf(s, "%s/%s", INDEX_DIR, NAME_LIST);
  693.     if((f_out = fopen(s, "w")) == NULL) {
  694.         fprintf(stderr, "can't open %s for writing\n", s);
  695.         exit(2);
  696.     }
  697.     sprintf(s, "%s/%s", INDEX_DIR, NAME_LIST_INDEX);
  698.     if((i_out = fopen(s, "w")) == NULL) {
  699.         fprintf(stderr, "can't open %s for writing\n", s);
  700.         exit(2);
  701.     }
  702.     fprintf(f_out, "%d\n", file_num);
  703.     for(i=0,offset=ftell(f_out); i<name_list_size; i++) {
  704.     if (LIST_GET(name_list, i) != NULL) {
  705.         putc((offset&0xff000000) >> 24, i_out);
  706.         putc((offset&0xff0000) >> 16, i_out);
  707.         putc((offset&0xff00) >> 8, i_out);
  708.         putc((offset&0xff), i_out);
  709.         fputs(LIST_GET(name_list, i), f_out);
  710.         putc('\n', f_out);
  711.         offset += strlen(LIST_GET(name_list, i)) + 1;
  712.     }
  713.     else {    /* else empty line to indicate file that was removed = HOLE */
  714.         if (name_list_size == file_num) {
  715.             putc((offset&0xff000000) >> 24, i_out);
  716.             putc((offset&0xff0000) >> 16, i_out);
  717.             putc((offset&0xff00) >> 8, i_out);
  718.             putc((offset&0xff), i_out);
  719.             putc('\n', f_out);
  720.             offset += 1;
  721.         }
  722.     }
  723.     /* else there are no holes since index was purged, so don't put anything */
  724.     }
  725.     fflush(f_out);
  726.     fclose(f_out);
  727.     fflush(i_out);
  728.     fclose(i_out);
  729.  
  730.     if (GenerateHash) {
  731.     /* Dump file hash: don't want to keep filenames in hash-order like index since adding a file can shift many hash-values and change the whole index! */
  732.     if (KeepFilenames) {
  733.     sprintf(s, "exec %s %s/%s %s/%s.prev", SYSTEM_CP, INDEX_DIR, NAME_HASH, INDEX_DIR, NAME_HASH);
  734.     system(s);
  735.     sprintf(s, "exec %s %s/%s %s/%s.prev", SYSTEM_CP, INDEX_DIR, NAME_HASH_INDEX, INDEX_DIR, NAME_HASH_INDEX);
  736.     system(s);
  737.     }
  738.     sprintf(s, "%s/%s", INDEX_DIR, NAME_HASH);
  739.     if((f_out = fopen(s, "w")) == NULL) {
  740.         fprintf(stderr, "can't open %s for writing\n", s);
  741.         exit(2);
  742.     }
  743.     sprintf(s, "%s/%s", INDEX_DIR, NAME_HASH_INDEX);
  744.     if((i_out = fopen(s, "w")) == NULL) {
  745.         fprintf(stderr, "can't open %s for writing\n", s);
  746.         exit(2);
  747.     }
  748.     if (!built_filename_hashtable) build_filename_hashtable(name_list, file_num);
  749.     for (i=0,offset=ftell(f_out); i<MAX_4K_HASH; i++) {
  750.     putc((offset&0xff000000) >> 24, i_out);
  751.     putc((offset&0xff0000) >> 16, i_out);
  752.     putc((offset&0xff00) >> 8, i_out);
  753.     putc((offset&0xff), i_out);
  754.     e = name_hashtable[i];
  755.     while(e!=NULL) {
  756.         if ((index = get_new_index(deletedlist, e->index)) < 0) {
  757.             e = e->next;
  758.             continue;
  759.         }
  760.         putc(((index)&0xff000000)>>24, f_out);
  761.         putc(((index)&0xff0000)>>16, f_out);
  762.         putc(((index)&0xff00)>>8, f_out);
  763.         putc(((index)&0xff), f_out);
  764.         offset += 4;
  765.         fputs(e->name, f_out);
  766.         fputc('\0', f_out);    /* so that I can do direct strcmp */
  767.         offset += strlen(e->name) + 1;
  768.         e = e->next;
  769.     }
  770.     }
  771.     fflush(f_out);
  772.     fclose(f_out);
  773.     fflush(i_out);
  774.     fclose(i_out);
  775.     }
  776.  
  777. #if    0
  778.     fflush(stdout);
  779.     printf("AFTER SAVE_DATA_STRUCTURES:\n");
  780.     sprintf(s, "exec %s -lg .glimpse_*", SYSTEM_LS);
  781.     system(s);
  782.     sprintf(s, "exec %s .glimpse_index", SYSTEM_WC);
  783.     system(s);
  784.     getchar();
  785. #endif    /*0*/
  786.  
  787.     return 0;
  788. }
  789.  
  790. /* Merges the index split by save_data_structures into a single index */
  791. merge_splits()
  792. {
  793.     FILE *i_in;
  794.     FILE *p_in;
  795.     FILE *i_out;
  796.     char s[MAX_LINE_LEN], s1[MAX_LINE_LEN];
  797.     int j, index;
  798.     unsigned char c;
  799.     char indexnumberbuf[256];
  800.     int onefileperblock, structuredindex, i;
  801.  
  802. #if    0
  803.     fflush(stdout);
  804.     printf("BEFORE MERGE_SPLITS:\n");
  805.     sprintf(s, "exec %s -lg .glimpse_*", SYSTEM_LS);
  806.     system(s);
  807.     sprintf(s, "exec %s .glimpse_index", SYSTEM_HEAD);
  808.     system(s);
  809.     getchar();
  810. #endif    /*0*/
  811.  
  812.     sprintf(s, "%s/%s", INDEX_DIR, P_TABLE);
  813.     if ((p_in = fopen(s, "r")) == NULL) {
  814.         fprintf(stderr, "cannot open for reading: %s\n", s);
  815.         exit(3);
  816.  
  817.     }
  818.  
  819.     sprintf(s, "%s/%s", INDEX_DIR, INDEX_FILE);
  820.     if ((i_in = fopen(s, "r")) == NULL) {
  821.         fprintf(stderr, "cannot open for reading: %s\n", s);
  822.         exit(3);
  823.     }
  824.     sprintf(s, "%s/.glimpse_merge.%d", INDEX_DIR, getpid());
  825.     if ((i_out = fopen(s, "w")) == NULL) {
  826.         fprintf(stderr, "cannot open for writing: %s\n", s);
  827.         exit(3);
  828.     }
  829.  
  830.     /* modified the original in glimpse's main.c */
  831.     fgets(indexnumberbuf, 256, i_in);
  832.     fputs(indexnumberbuf, i_out);
  833.     fscanf(i_in, "%%%d\n", &onefileperblock);
  834.     fprintf(i_out, "%%%d\n", onefileperblock);
  835.     fscanf(i_in, "%%%d\n", &structuredindex);
  836.     if (structuredindex <= 0) structuredindex = 0;
  837.     fprintf(i_out, "%%%d\n", structuredindex);
  838.  
  839. #if    !WORD_SORTED
  840.     if (!DeleteFromIndex || FastIndex) {    /* a new index is going to be built in this case: must sort by word */
  841.         fclose(i_in);
  842.         sprintf(s, "%s/%s", INDEX_DIR, MINI_FILE);
  843.         if ((i_in = fopen(s, "r")) != NULL) {    /* minifile exists */
  844. #if    DONTUSESORT_T_OPTION || SFS_COMPAT
  845.             sprintf(s, "exec %s %s/%s > %s/%s.tmp", SYSTEM_SORT, INDEX_DIR, INDEX_FILE, INDEX_DIR, INDEX_FILE);
  846. #else
  847.             sprintf(s, "exec %s -T %s %s/%s > %s/%s.tmp", SYSTEM_SORT, INDEX_DIR, INDEX_DIR, INDEX_FILE, INDEX_DIR, INDEX_FILE);
  848. #endif
  849.             system(s);
  850. #if    SFS_COMPAT
  851.             sprintf(s, "%s/%s.tmp", INDEX_DIR, INDEX_FILE);
  852.             sprintf(s1, "%s/%s", INDEX_DIR, INDEX_FILE);
  853.             rename(s, s1);
  854. #else
  855.             sprintf(s, "exec %s %s/%s.tmp %s/%s", SYSTEM_MV, INDEX_DIR, INDEX_FILE, INDEX_DIR, INDEX_FILE);
  856.             system(s);
  857. #endif
  858.             system(sync_path);    /* sync() has a BUG */
  859.             fclose(i_in);
  860.         }
  861.         sprintf(s, "%s/%s", INDEX_DIR, INDEX_FILE);
  862.         if ((i_in = fopen(s, "r")) == NULL) {
  863.             fprintf(stderr, "cannot open for reading: %s\n", s);
  864.             exit(3);
  865.         }
  866.         /* skip the 1st 3 lines which might get jumbled up */
  867.         fgets(s, MAX_LINE_LEN, i_in);
  868.         fgets(s, MAX_LINE_LEN, i_in);
  869.         fgets(s, MAX_LINE_LEN, i_in);
  870.     }
  871. #endif    /* !WORD_SORTED */
  872.  
  873.     while (fgets(src_index_buf, REAL_INDEX_BUF, i_in)) {
  874.         j = 0;
  875.         while ((j < REAL_INDEX_BUF) && (src_index_buf[j] != WORD_END_MARK) && (src_index_buf[j] != ALL_INDEX_MARK) && (src_index_buf[j] != '\0') && (src_index_buf[j] != '\n')) j++;
  876.         if ((j >= REAL_INDEX_BUF) || (src_index_buf[j] == '\0') || (src_index_buf[j] == '\n')) continue;
  877.         /* else it is WORD_END_MARK or ALL_INDEX_MARK */
  878.         c = src_index_buf[j+1];
  879.         src_index_buf[j+1] = '\0';
  880.         fputs(src_index_buf, i_out);
  881.         src_index_buf[j+1] = c;
  882.         c = src_index_buf[j];
  883.         if (structuredindex) {    /* convert all attributes to 2B to make merge_in()s easy in build_in.c */
  884.         if (structuredindex < MaxNum8bPartition - 1) {
  885.             index = encode16b(decode8b(src_index_buf[j+1]));
  886.             putc((index & 0x0000ff00) >> 8, i_out);
  887.             putc(index & 0x000000ff, i_out);
  888.             j ++;
  889.         }
  890.         else {
  891.             putc(src_index_buf[j+1], i_out);
  892.             putc(src_index_buf[j+2], i_out);
  893.             j += 2;
  894.         }
  895.         }
  896.         if (c == ALL_INDEX_MARK) {
  897.         putc(DONT_CONFUSE_SORT, i_out);
  898.         putc('\n', i_out);
  899.         continue;
  900.         }
  901.  
  902.         /* src_index_buf[j+1] points to the first byte of the offset */
  903.         get_block_numbers(&src_index_buf[j+1], &dest_index_buf[0], p_in);
  904.         j = 0;    /* first byte of the block numbers */
  905.         while ((dest_index_buf[j] != '\n') && (dest_index_buf[j] != '\0')) {
  906.         putc(dest_index_buf[j], i_out);
  907.         dest_index_buf[j] = '\0';
  908.         j++;
  909.         }
  910.         if (putc('\n', i_out) == EOF) {
  911.         fprintf(stderr, "Error: write failed at %s:%d\n", __FILE__, __LINE__);
  912.         exit(2);
  913.         }
  914.     }
  915.  
  916.     fclose(i_in);
  917.     fclose(p_in);
  918.     fflush(i_out);
  919.     fclose(i_out);
  920. #if    SFS_COMPAT
  921.     sprintf(s, "%s/.glimpse_merge.%d", INDEX_DIR, getpid());
  922.     sprintf(s1, "%s/%s", INDEX_DIR, INDEX_FILE);
  923.     rename(s, s1);
  924. #else
  925.     sprintf(s, "exec %s %s/.glimpse_merge.%d %s/%s", SYSTEM_MV, INDEX_DIR, getpid(), INDEX_DIR, INDEX_FILE);
  926.     system(s);
  927. #endif
  928.  
  929. #if    0
  930.     fflush(stdout);
  931.     printf("AFTER MERGE_SPLITS:\n");
  932.     sprintf(s, "exec %s -lg .glimpse_*", SYSTEM_LS);
  933.     system(s);
  934.     sprintf(s, "exec %s .glimpse_index"SYSTEM_HEAD);
  935.     system(s);
  936.     getchar();
  937. #endif    /*0*/
  938. }
  939.  
  940.